package daobeauty.proxy;

import org.hibernate.SessionFactory;
import org.hibernate.bytecode.BytecodeProvider;

import daobeauty.proxy.reflection.ReflectionProxyProvider;


/**
 * Primary interaction point to the user of the daobeauty project. Basically 
 * proxies are attached to DAO interfaces, which then make use of the 
 * underlying querying functionality, mapping etc.   
 * 
 * Created 08.09.2008
 * @author M. Serhat Cinar
 *
 */
public class ProxyFactory {
	private boolean useByteCodeProviderForInterfaces = false;
	private ProxyProvider byteCodeProvider;
	
	/**
	 * Instantiates a {@link ProxyFactory} using the default 
	 * {@link BytecodeProvider}s. See {@link ByteCodeProviders#getInstance()}
	 */
	public ProxyFactory(){}
	
	public ProxyFactory(String byteCodeProvider){
		this.byteCodeProvider = ByteCodeProviders.getInstance(byteCodeProvider);
	}
	
	public ProxyFactory(ProxyProvider byteCodeProvider){
		this.byteCodeProvider = byteCodeProvider;
	}
	
	public ProxyFactory(boolean useByteCodeProviderForInterfaces){
		this.useByteCodeProviderForInterfaces = useByteCodeProviderForInterfaces; 
	}
	
	public ProxyFactory(String byteCodeProvider, boolean useByteCodeProviderForInterfaces){
		this.byteCodeProvider = ByteCodeProviders.getInstance(byteCodeProvider);
		this.useByteCodeProviderForInterfaces = useByteCodeProviderForInterfaces;
	}
	
	public ProxyFactory(ProxyProvider byteCodeProvider, boolean useByteCodeProviderForInterfaces){
		this.byteCodeProvider = byteCodeProvider;
		this.useByteCodeProviderForInterfaces = useByteCodeProviderForInterfaces;
	}
	
	/**
	 * 
	 * @param interfaces The Dao interface(s) for which proxies shall be 
	 * 					 generated. Please note that multiple daos with 
	 * 					 different method subsets are supported.  
	 * @param sessionFactory The Hibernate Session factory to which the 
	 * 						 proxy will send queries to. 
	 * @param domainClass The base Domain class, basically the Hibernate 
	 * 					  Pojo class on which the intended proxy shall operate.
	 * @param target 
	 * @param delegates Override Dao operations on the interface through a 
	 * 					native java implementation.
	 * @return A proxy implementing all given dao interfaces.
	 */
	public Object generateProxy(Class[] interfaces, SessionFactory sessionFactory, Class domainClass, Object target, Object [] delegates){
		if (target==null){
			if (!useByteCodeProviderForInterfaces){
				// TODO cache this too
				byteCodeProvider = new ReflectionProxyProvider();
			}
		}
		if (byteCodeProvider==null){
			byteCodeProvider = ByteCodeProviders.getInstance();
		}
		return byteCodeProvider.generateProxy(interfaces, sessionFactory, domainClass, target, delegates);
	}
}